package com.dage;

import com.jfinal.core.JFinal;
import com.jfinal.kit.JavaKeyword;
import com.jfinal.kit.Kv;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.dialect.MysqlDialect;
import com.jfinal.plugin.activerecord.generator.TableMeta;
import com.jfinal.template.Engine;
import com.jfinal.template.source.ClassPathSourceFactory;
import io.jboot.codegen.CodeGenHelpler;
import io.jboot.exception.JbootException;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MyServiceGenerator {

	private final String projectPackage;
	private MyMetaBuilder metaBuilder;

	private String template;
	private String outputDir;

	public MyServiceGenerator(String projectPackage, String outputDir) {
		this.projectPackage = projectPackage;
		this.template = "service_template.tp";
		MyMetaBuilder metaBuilder = new MyMetaBuilder(CodeGenHelpler.getDatasource());
		metaBuilder.setDialect(new MysqlDialect());
		metaBuilder.setRemovedTableNamePrefixes("t_");
		metaBuilder.setGenerateRemarks(true);
		this.metaBuilder = metaBuilder;
		this.outputDir = outputDir;
	}

	public void generate() {
		generate(metaBuilder.build(true));
	}

	/**
	 * 设置需要被移除的表名前缀
	 * 例如表名  "tb_account"，移除前缀 "tb_" 后变为 "account"
	 */
	public MyServiceGenerator setRemovedTableNamePrefixes(String... prefixes) {
		metaBuilder.setRemovedTableNamePrefixes(prefixes);
		return this;
	}

	public MyServiceGenerator addExcludedTable(String... excludedTables) {
		metaBuilder.addExcludedTable(excludedTables);
		return this;
	}

	public MyServiceGenerator addWhitelist(String... tableNames) {
		if (tableNames != null) {
			this.metaBuilder.addWhitelist(tableNames);
		}
		return this;
	}

	public MyServiceGenerator setGenerateRemarks(boolean generateRemarks) {
		metaBuilder.setGenerateRemarks(generateRemarks);
		return this;
	}

	public void generate(List<TableMeta> tableMetas) {
		System.out.println("Generate Service Impl ...");
		System.out.println("Service Impl Output Dir: " + outputDir);

		Engine engine = Engine.create("forServiceImpl");
		engine.setSourceFactory(new ClassPathSourceFactory());
		engine.addSharedMethod(new StrKit());
		engine.addSharedObject("getterTypeMap", getterTypeMap);
		engine.addSharedObject("javaKeyword", JavaKeyword.me);

		for (TableMeta tableMeta : tableMetas) {
			genContent(tableMeta);
		}
		writeToFile(tableMetas);
	}

	protected void genContent(TableMeta tableMeta) {
		Kv data = Kv.by("tableMeta", tableMeta);
		data.set("projectPackage", projectPackage);
		Engine engine = Engine.use("forServiceImpl");
		tableMeta.baseModelContent = engine.getTemplate(template).renderToString(data);
	}

	protected void writeToFile(List<TableMeta> tableMetas) {
		try {
			for (TableMeta tableMeta : tableMetas) {
				writeToFile(tableMeta);
			}
		} catch (IOException e) {
			throw new JbootException(e);
		}
	}

	/**
	 * 覆盖写入
	 */
	protected void writeToFile(TableMeta tableMeta) throws IOException {
		File dir = new File(outputDir);
		if (!dir.exists()) {
			dir.mkdirs();
		}

		String target = outputDir + File.separator + tableMeta.modelName + "Service.java";

		//		File targetFile = new File(target);
		//		if (targetFile.exists()) {
		//			return;
		//		}

		try (OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(target), JFinal.me().getConstants().getEncoding())) {
			osw.write(tableMeta.baseModelContent);
		}

	}

	protected Map<String, String> getterTypeMap = new HashMap<String, String>() {{
		put("java.lang.String", "getStr");
		put("java.lang.Integer", "getInt");
		put("java.lang.Long", "getLong");
		put("java.lang.Double", "getDouble");
		put("java.lang.Float", "getFloat");
		put("java.lang.Short", "getShort");
		put("java.lang.Byte", "getByte");
	}};
}
